package logger

import (
	"github.com/golang-module/carbon/v2"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"os"
	"time"
)

func New(config *Config) *zap.Logger {
	encoder := getEncoder()
	writeSyncer := getWriteSyncer(config)
	level := config.Level
	return zap.New(zapcore.NewCore(encoder, writeSyncer, zap.NewAtomicLevelAt(getLevel(level)))).WithOptions(
		zap.AddCaller(),
		zap.AddStacktrace(zap.NewAtomicLevelAt(zap.ErrorLevel)),
	)
}

func getLevel(level string) zapcore.Level {

	switch level {
	case "debug":
		return zap.DebugLevel
	case "info":
		return zap.InfoLevel
	case "warn":
		return zap.WarnLevel
	case "error":
		return zap.ErrorLevel
	case "panic":
		return zap.PanicLevel
	case "fatal":
		return zap.FatalLevel
	default:
		return zap.DebugLevel
	}
}

func getEncoder() zapcore.Encoder {
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:       "T",
		LevelKey:      "L",
		NameKey:       "name",
		CallerKey:     "C",
		FunctionKey:   zapcore.OmitKey,
		MessageKey:    "msg",
		StacktraceKey: "trace",
		LineEnding:    zapcore.DefaultLineEnding,
		EncodeLevel:   zapcore.CapitalLevelEncoder,
		EncodeTime: func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {
			encoder.AppendString(carbon.Now().ToDateTimeMilliString())
		},
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
		EncodeName:     zapcore.FullNameEncoder,
	}
	return zapcore.NewConsoleEncoder(encoderConfig)
}

func getWriteSyncer(config *Config) zapcore.WriteSyncer {
	lg := lumberjack.Logger{
		Filename:   config.Filepath + "log.log",
		MaxSize:    config.MaxSize,    //日志最大的大小（M）
		MaxBackups: config.MaxBackups, //备份个数
		MaxAge:     config.MaxAge,     //最大保存天数（day）
		Compress:   config.Compress,   //是否压缩
		LocalTime:  config.Localtime,
	}

	var writers []zapcore.WriteSyncer
	if config.Stdout {
		writers = append(writers, zapcore.AddSync(os.Stdout))
	}
	writers = append(writers, zapcore.AddSync(&lg))
	syncer := zapcore.NewMultiWriteSyncer(
		writers...,
	)
	return syncer
}
